/*
 * Copyright (c) 2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "service_sec_storage.h"

#include <securec.h>

#include "dyn_services_card_channel.h"
#include "dyn_services_core.h"
#include "logger.h"
#include "se_base_services_defines.h"
#include "sec_storage_ipc_stub.h"
#include "service_sec_storage_func.h"

#define SEC_STORAGE_APPLET_AID                                                                         \
    {                                                                                                  \
        0xf0, 0x00, 0x00, 0x48, 0x4d, 0x53, 0x45, 0x43, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x00 \
    }

#define SEC_STORAGE_READER_NAME "eSE_spi_0"

ResultCode SecStorageCheckPermission(uint32_t sender, uint32_t sid, uint32_t cmd)
{
    const TEE_UUID list[] = {PIN_AUTH_TA_UUID};

    if (CheckClientPermission(sender, list, sizeof(list) / sizeof(TEE_UUID)) != SUCCESS) {
        LOG_ERROR("error for CheckClientPermission, sid = 0x%x, cmd = 0x%x", sid, cmd);
        return INVALID_PERM;
    }
    return SUCCESS;
}

ResultCode SecStorageProcessCommand(uint32_t sender, uint32_t cmd, SharedDataBuffer *sharedData)
{
    if (sharedData == NULL) {
        return INVALID_PARA_NULL_PTR;
    }

    LOG_INFO("invoked, cmd=0x%x, dataSize=%u, dataMaxSize=%u", cmd, sharedData->dataSize, sharedData->dataMaxSize);

    uint8_t aid[] = SEC_STORAGE_APPLET_AID;
    AppIdentifier identifier = {.aid = aid, .aidLen = sizeof(aid)};
    CardChannel *channel = CreateSecureElementChannel(SEC_STORAGE_READER_NAME, &identifier);
    if (channel == NULL) {
        LOG_ERROR("CreateSecureElementChannel error");
        return CHN_OPEN_ERR;
    }

    SecStorageContext context;
    (void)memset_s(&context, sizeof(context), 0, sizeof(context));

    INIT_SE_COMMON_CONTEXT(context.base, sender, channel);
    context.derive = StorageKeyDerive;
    context.slotIdGetter = SecStorageGetSlotIdByName;

    ResultCode ret = ProcessSecStorageCommandStub(&context, cmd, sharedData);
    DestroySecureElementChannel(channel);
    return ret;
}

SERVICE_REGISTER(SERVICE_ID_SEC_STORAGE, SecStorageProcessCommand, SecStorageCheckPermission);
